﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using ArcEngine.Graphics;
using ArcEngine.Input;


namespace ArcEngine.Forms
{
	/// <summary>
	/// Rendering form
	/// </summary>
	public partial class RenderForm : Form
	{
		public RenderForm()
		{
			InitializeComponent();
			SetStyle(ControlStyles.UserPaint, true);
			SetStyle(ControlStyles.AllPaintingInWmPaint, true);
			this.SetStyle(ControlStyles.Opaque, true);


			GlControl.InitializeContexts();


			Application.Idle += new EventHandler(OnApplicationIdle); 

		}


		#region Rendering loop

		/// <summary>
		/// https://blogs.msdn.com/tmiller/archive/2005/05/05/415008.aspx
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		void OnApplicationIdle(object sender, EventArgs e)
		{
			// If no level active, no update
			//if (ResourceManager.CurrentLevel == null)
			//    return;

			while (AppStillIdle)
			{
				// Update the engine
				Video.Update();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		private bool AppStillIdle
		{
			get
			{
				Message msg;
				return !PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
			}
		}


		/// <summary>
		/// 
		/// </summary>
		[StructLayout(LayoutKind.Sequential)]
		public struct Message
		{
			public IntPtr hWnd;
			public IntPtr msg;
			public IntPtr wParam;
			public IntPtr lParam;
			public uint time;
			public Point p;
		}

		/// <summary>
		/// Import the User32.dll to get the PeekMessage method 
		/// </summary>
		/// <param name="msg"></param>
		/// <param name="hWnd"></param>
		/// <param name="messageFilterMin"></param>
		/// <param name="messageFilterMax"></param>
		/// <param name="flags"></param>
		/// <returns></returns>
		[System.Security.SuppressUnmanagedCodeSecurity]
		[DllImport("User32.dll", CharSet = CharSet.Auto)]
		public static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags); 

		#endregion


		#region Keyboard events

		/// <summary>
		/// OnKeyUp event
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnKeyUp(object sender, KeyEventArgs e)
		{
			Keyboard.KeyUp(e);
		}

		/// <summary>
		/// OnKeyDown event
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void GlControl_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
		{
			Keyboard.KeyDown(e);
		}

		#endregion


		#region Mouse events

		/// <summary>
		/// OnMouseDown event
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnMouseDown(object sender, MouseEventArgs e)
		{
			Mouse.ButtonDown(e);
		}

		/// <summary>
		/// OnMouseMove event
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnMouseMove(object sender, MouseEventArgs e)
		{
			Mouse.Move(e);
		}

		/// <summary>
		/// OnMouseUp event
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnMouseUp(object sender, MouseEventArgs e)
		{
			Mouse.ButtonUp(e);

		}

		/// <summary>
		///  OnMouseDoubleClick
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void OnMouseDoubleClick(object sender, MouseEventArgs e)
		{
			Mouse.DoubleClick(e);
		}

		#endregion


		#region Events
		/// <summary>
		/// OnResize
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void GlControl_Resize(object sender, EventArgs e)
		{
			GlControl.MakeCurrent();
			Video.ViewPort = new Rectangle(new Point(), GlControl.Size);
		}



		#endregion
	}
}
